package net.xdclass.service.impl;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.constant.CacheKey;
import net.xdclass.enums.BizCodeEnum;
import net.xdclass.exception.BizException;
import net.xdclass.interceptor.LoginInterceptor;
import net.xdclass.model.LoginUser;
import net.xdclass.request.CartItermRequest;
import net.xdclass.service.CartService;
import net.xdclass.service.ProductService;
import net.xdclass.vo.CartItemVO;
import net.xdclass.vo.CartVO;
import net.xdclass.vo.ProductVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : zhen.xue
 * @date : 2021-05-28 16:13
 */
@Slf4j
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductService productService;

    @Override
    public void addToCart(CartItermRequest cartItermRequest) {
        int byNum = cartItermRequest.getBuyNum();
        long productId = cartItermRequest.getProductId();
        BoundHashOperations<String, Object, Object> myCart = getMyCartOps();
        Object cacheObject = myCart.get(productId);
        String result = "";
        if (cacheObject != null){
            result = (String) cacheObject;
        }
        if(StringUtils.isBlank(result)){
            // 不存在测新建一个商品
            CartItemVO cartItemVO = new CartItemVO();
            ProductVO productVO = productService.findDetailById(productId);
            if(productVO == null){
                throw new BizException(BizCodeEnum.CART_FAIL);
            }
            cartItemVO.setProductId(productId);
            cartItemVO.setBuyNum(byNum);
            cartItemVO.setProductTitle(productVO.getTitle());
            cartItemVO.setProductImg(productVO.getCoverImg());
            cartItemVO.setAmount(productVO.getAmount());
            myCart.put(productId, JSON.toJSONString(cartItemVO));
        }else{
            // 存在商品则修改数量
            CartItemVO cartItem = JSON.parseObject(result, CartItemVO.class);
            cartItem.setBuyNum(cartItem.getBuyNum() + byNum);
            myCart.put(productId, JSON.toJSONString(cartItem));
        }
    }

    @Override
    public void clear() {
        String cartKey = getCartKey();
        redisTemplate.delete(cartKey);
    }

    @Override
    public CartVO findMyCart() {
        // 获取全部的购物项
        List<CartItemVO> cartItemVOList = buildcartItem(false);
        CartVO cartVO = new CartVO();
        cartVO.setCartItems(cartItemVOList);
        return cartVO;
    }

    @Override
    public void deleteItem(long productId) {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        myCartOps.delete(productId);
    }

    @Override
    public void changeItemNum(CartItermRequest cartItermRequest) {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        String obj = (String) myCartOps.get(cartItermRequest.getProductId());
        if (obj == null) {
           throw new BizException(BizCodeEnum.CART_FAIL);
        }
        CartItemVO cartItemVO = JSON.parseObject(obj, CartItemVO.class);
        cartItemVO.setBuyNum(cartItermRequest.getBuyNum());
        myCartOps.put(cartItermRequest.getProductId(),JSON.toJSONString(cartItemVO));
    }

    @Override
    public List<CartItemVO> confirmOrderCartItems(List<Long> productIdList) {
        // 获取全部购物车的购物项
        List<CartItemVO> cartItemVOList = buildcartItem(true);
        // 根据需要的商品id进行过滤，并清空对应的购物项
        List<CartItemVO> cartItemResultList = cartItemVOList.stream().filter(obj -> {
            if(productIdList.contains(obj.getProductId())){
                // 清除购物车中的数据
                this.deleteItem(obj.getProductId());
                return true;
            }
            return false;
        }).collect(Collectors.toList());
        return cartItemResultList;
    }


    /**
     * 获取最新购物项
     * @param latestPrice 是否获取最新的价格
     * @return
     */
    private List<CartItemVO> buildcartItem(boolean latestPrice) {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        List<Object> itemList = myCartOps.values();
        List<CartItemVO> cartItemVOList = new ArrayList<>();
        // 拼接id列表查询最新价格
        List<Long> productIdList = new ArrayList<>();
        if (itemList != null) {
            for (Object item : itemList) {
                CartItemVO cartItemVO = JSON.parseObject((String) item, CartItemVO.class);
                cartItemVOList.add(cartItemVO);
                productIdList.add(cartItemVO.getProductId());
            }
        }
        // 是否需要查询最新的价格
        if(latestPrice){
            setProductLatesPrice(cartItemVOList,productIdList);
        }
        return cartItemVOList;
    }


    /**
     * 设置商品最新价格
     * @param cartItemVOList 全部购物项
     * @param productIdList 商品id集合
     */
    private void setProductLatesPrice(List<CartItemVO> cartItemVOList, List<Long> productIdList) {
        // 批量查询
        List<ProductVO> productVOList = productService.findProductsByIdBatch(productIdList);
        // 变成map
        Map<Long, ProductVO> productVOMap = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));
        cartItemVOList.forEach(item->{
            ProductVO productVO = productVOMap.get(item.getProductId());
            item.setProductImg(productVO.getCoverImg());
            item.setAmount(productVO.getAmount());
            item.setProductTitle(productVO.getTitle());
        });
    }


    /**
     * 抽取我的购物车通用方法
     * @return
     */
    private BoundHashOperations<String,Object,Object> getMyCartOps(){
        String cartKey = getCartKey();
        return redisTemplate.boundHashOps(cartKey);
    }


    /**
     * 获取购物车key
     * @return
     */
    private String getCartKey(){
        LoginUser user = LoginInterceptor.threadLocal.get();
        String cartKey = String.format(CacheKey.CART_KEY,user.getId());
        return cartKey;
    }
}